package com.ky.serialport.service;

import android.app.Application;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.Log;

import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.clj.fastble.scan.BleScanRuleConfig;
import com.ky.myserialport.R;
import com.ky.serialport.utils.MyFunc;

import java.util.List;

public class BlueToothManager {

    private Context mContext;
    private boolean _All; //是否断开重连
    private boolean isRun = true; //优利德 请求数据线程控制
    private boolean isConntedNotify = false; //优利德 监听打开
    public static BluetoothGattCharacteristic writeDtBGC;
    public static BluetoothGattCharacteristic notifyDtBgc;
    public static BluetoothGattCharacteristic writeUldBGC;
    public static BluetoothGattCharacteristic notifyUldBgc;

    public static BleDevice mDtDevice = null;
    public static BleDevice mUldDevice = null;
    public static String mDtMAC = null;
    public static String mUldMAC = null;

    private OnGetDataListener onGetDataListener;
    private OnConnectedListener onConnectedListener;
    private OnDisConnectedListener onDisConnectedListener;
    final String[] msgArray;
    private String TAG = "蓝牙设备";


    public BlueToothManager(Context mContext, boolean _All) {
        this.mContext = mContext;
        this._All = _All;
        msgArray = mContext.getResources().getStringArray(R.array.msgArray);
    }

    public void initBlueTooth(final Application mApplication) {

        BleManager.getInstance().init(mApplication);
        BleManager.getInstance()
                .enableLog(true)
                //设置连接时重连次数和重连间隔（毫秒），默认为0次不重连
                .setReConnectCount(50, 2000)
                //设置分包发送的时候，每一包的数据长度，默认20个字节
                .setSplitWriteNum(20)
                //设置连接超时时间（毫秒），默认10秒
                .setConnectOverTime(30000)
                //设置readRssi、setMtu、write、read、notify、indicate的超时时间（毫秒），默认5秒
                .setOperateTimeout(50000);
        //主动打开蓝牙。
//        if (!BleManager.getInstance().isBlueEnable()) {
//            BleManager.getInstance().enableBluetooth();
//            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
//            mActivity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
//        }
        //配置扫描规则
        BleScanRuleConfig scanRuleConfig = new BleScanRuleConfig.Builder()
                //.setServiceUuids(serviceUuids)      // 只扫描指定的服务的设备，可选
                //.setDeviceName(true, names)         // 只扫描指定广播名的设备，可选
                //.setDeviceMac(mac)                  // 只扫描指定mac的设备，可选
                .setAutoConnect(false)      // 连接时的autoConnect参数，可选，默认false
                .setScanTimeOut(0)              // 扫描超时时间，可选，默认10秒；小于等于0表示不限制扫描时间
                .build();
        BleManager.getInstance().initScanRule(scanRuleConfig);

        //扫描监听
        BleManager.getInstance().scan(new com.clj.fastble.callback.BleScanCallback() {
            @Override
            public void onScanFinished(List<BleDevice> scanResultList) {
                // 扫描结束，列出所有扫描到的符合扫描规则的BLE设备（主线程）
                Log.d(TAG, "扫描结束，列出所有扫描到的符合扫描规则的BLE设备（主线程）");
            }

            @Override
            public void onScanStarted(boolean success) {
                // 开始扫描（主线程）
                Log.d(TAG, "onScanStarted: 开始扫描（主线程 ");
            }

            @Override
            public void onScanning(final BleDevice bleDevice) {
                //扫描到一个符合扫描规则的BLE设备（主线程）
                if (bleDevice.getName() == null) return;

                if (bleDevice != null && bleDevice.getName() != null && bleDevice.getName().startsWith("T405i") || bleDevice.getName().startsWith("T410i") || bleDevice.getName().startsWith("T805i")) {
                    mDtDevice = bleDevice;
                    mDtMAC = bleDevice.getMac();
                    Log.d(TAG, "onScanning:扫描到仪器 " + bleDevice.getName());
                    BleManager.getInstance().connect(bleDevice, new BleGattCallback() {
                        @Override
                        public void onStartConnect() {
                            Log.d(TAG, "onStartConnect: 蓝牙开始连接" + bleDevice.getName());
                        }

                        @Override
                        public void onConnectFail(BleDevice bleDevice, BleException exception) {
                            Log.d(TAG, "onConnectFail:蓝牙连接失败 " + bleDevice.getName());
                        }

                        @Override
                        public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt bluetoothGatt, int status) {
                            Log.d(TAG, "onConnectSuccess: 连接成功并发现服务" + bleDevice.getName());
                            List<BluetoothGattService> serviceList = bluetoothGatt.getServices();
                            if (serviceList == null) return;
                            writeDtBGC = serviceList.get(3).getCharacteristics().get(0);
                            notifyDtBgc = serviceList.get(3).getCharacteristics().get(1);
                            openNotify(bleDevice, notifyDtBgc);
                        }

                        @Override
                        public void onDisConnected(boolean isActiveDisConnected, BleDevice device, BluetoothGatt gatt, int status) {
                            // 连接中断，isActiveDisConnected表示是否是主动调用了断开连接方法
                            Log.d(TAG, "onDisConnected: 蓝牙连接后断开 " + device.getName() + " ---》 是否主动断开 ：" + isActiveDisConnected);
                            if (onDisConnectedListener != null) {
                                if (bleDevice.getName().startsWith("T405i")){
                                    onDisConnectedListener.disConnected("T405i", System.currentTimeMillis());
                                }
                                if (bleDevice.getName().startsWith("T410i")){
                                    onDisConnectedListener.disConnected("T410i", System.currentTimeMillis());
                                }
                                if (bleDevice.getName().startsWith("T805i")){
                                    onDisConnectedListener.disConnected("T805i", System.currentTimeMillis());
                                }

                            }
                            if (mDtMAC != null) {
                                reconnect(bleDevice.getName(), mDtMAC);
                            }
                        }
                    });
                }
                // 光照仪器
                if (bleDevice.getName() != null && bleDevice.getName().startsWith("UT383BT")) {
                    Log.d(TAG, "onScanning: 扫描到光照仪器 UT383BT");
                    mUldDevice = bleDevice;
                    mUldMAC = bleDevice.getMac();
                    BleManager.getInstance().connect(bleDevice, new BleGattCallback() {
                        @Override
                        public void onStartConnect() {
                            //开始连接
                            Log.d(TAG, "onStartConnect: 照仪器开始连接");
                        }

                        @Override
                        public void onConnectFail(BleDevice bleDevice, BleException exception) {
                            //连接失败
                            Log.d(TAG, "onConnectFail: 照仪器蓝牙连接失败");
                        }

                        @Override
                        public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt bluetoothGatt, int status) {
                            //连接成功
                            Log.d(TAG, "onConnectSuccess: 照仪器连接成功并发现服务");
                            List<BluetoothGattService> serviceList = bluetoothGatt.getServices();
                            if (serviceList == null) return;
                            writeUldBGC = serviceList.get(3).getCharacteristics().get(0);
                            notifyUldBgc = serviceList.get(3).getCharacteristics().get(1);
                            openNotify(bleDevice, notifyUldBgc);
                            //第一次连接成功后发送请求数据命令
                            sendAsk();
                        }

                        @Override
                        public void onDisConnected(boolean isActiveDisConnected, BleDevice device, BluetoothGatt gatt, int status) {
                            // 连接中断，isActiveDisConnected表示是否是主动调用了断开连接方法
                            Log.d(TAG, "蓝牙连接后断开 " + isActiveDisConnected);
                            if (onDisConnectedListener != null) {
                                onDisConnectedListener.disConnected(bleDevice.getName(), System.currentTimeMillis());
                            }
                            if (mUldMAC != null) {
                                reconnect(bleDevice.getName(), mUldMAC);
                            }
                        }
                    });
                }

            }
        });
    }

    private void reconnect(final String type, String mac) {

        BleManager.getInstance().connect(mac, new BleGattCallback() {
            @Override
            public void onStartConnect() {
                // 开始连接
                Log.d(TAG, type + "重新开始连接");
            }

            @Override
            public void onConnectFail(BleDevice bleDevice, BleException exception) {
                // 连接失败
                Log.d(TAG, type + "重新连接失败");
            }

            @Override
            public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt bluetoothGatt, int status) {
                if (bleDevice.getName().startsWith("T405i") || bleDevice.getName().startsWith("T410i") || bleDevice.getName().startsWith("T805i")){
                    //连接成功
                    Log.d(TAG, "onConnectSuccess: 重新连接成功并发现服务" + bleDevice.getName());
                    mDtDevice = bleDevice;
                    mDtMAC = bleDevice.getMac();
                    List<BluetoothGattService> serviceList = bluetoothGatt.getServices();
                    if (serviceList == null) return;
                    writeDtBGC = serviceList.get(3).getCharacteristics().get(0);
                    notifyDtBgc = serviceList.get(3).getCharacteristics().get(1);
                    openNotify(bleDevice, notifyDtBgc);
                }

                if (bleDevice.getName().startsWith("UT383BT")){
                    Log.d(TAG, "onConnectSuccess: 重新连接成功并发现服务" + bleDevice.getName());
                    List<BluetoothGattService> serviceUldList = bluetoothGatt.getServices();
                    if (serviceUldList == null) return;
                    writeUldBGC = serviceUldList.get(3).getCharacteristics().get(0);
                    notifyUldBgc = serviceUldList.get(3).getCharacteristics().get(1);
                    openNotify(bleDevice, notifyUldBgc);
                }
            }

            @Override
            public void onDisConnected(boolean isActiveDisConnected, BleDevice bleDevice, BluetoothGatt gatt, int status) {
                // 连接中断，isActiveDisConnected表示是否是主动调用了断开连接方法
                Log.d(TAG, "onDisConnected: 连接中断 （是否主动断开） " + isActiveDisConnected);
                mUldDevice = bleDevice;
                mUldMAC = bleDevice.getMac();
                if (onDisConnectedListener != null) {
                    if (bleDevice.getName().startsWith("UT383BT")){
                        onDisConnectedListener.disConnected("UT383BT", System.currentTimeMillis());
                    }
                    if (bleDevice.getName().startsWith("T405i")){
                        onDisConnectedListener.disConnected("T405i", System.currentTimeMillis());
                    }
                    if (bleDevice.getName().startsWith("T410i")){
                        onDisConnectedListener.disConnected("T410i", System.currentTimeMillis());
                    }
                    if (bleDevice.getName().startsWith("T805i")){
                        onDisConnectedListener.disConnected("T805i", System.currentTimeMillis());
                        isConntedNotify = false;
                    }
                }
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(3000);
                            if (_All) {
                                if (mDtMAC != null)
                                    reconnect(type, mDtMAC);
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        });
    }

    private void openNotify(final BleDevice bleDevice, BluetoothGattCharacteristic notifyBgc) {
        if (bleDevice == null || notifyBgc == null) {
            return;
        }
        //打开notify
        BleManager.getInstance().notify(
                bleDevice,
                notifyBgc.getService().getUuid().toString(),
                notifyBgc.getUuid().toString(),
                new BleNotifyCallback() {
                    @Override
                    public void onNotifySuccess() {
                        // 打开通知操作成功
                        Log.d(TAG, "onNotifySuccess: 蓝牙打开通知操作成功" + bleDevice.getName());
                        if (onConnectedListener != null) {
                            if (bleDevice.getName().startsWith("T405i")){
                                onConnectedListener.connected("T405i", System.currentTimeMillis());
                            }
                            if (bleDevice.getName().startsWith("T410i")){
                                onConnectedListener.connected("T410i", System.currentTimeMillis());
                            }
                            if (bleDevice.getName().startsWith("T805i")){
                                onConnectedListener.connected("T805i", System.currentTimeMillis());
                            }

                            if (bleDevice.getName().startsWith("UT383BT")){
                                onConnectedListener.connected("UT383BT", System.currentTimeMillis());
                                isConntedNotify = true;
                            }
                        }

                        if (bleDevice.getName().startsWith("T405i") || bleDevice.getName().startsWith("T410i") || bleDevice.getName().startsWith("T805i")){
                            new Thread(new Runnable() {
                                @Override
                                public void run() {
                                    int sendmsg_num = 0;
                                    while (sendmsg_num < 5) {
                                        try {
                                            Thread.sleep(1000);
                                        } catch (InterruptedException e) {
                                            e.printStackTrace();
                                        }
                                        sendHexToDt(msgArray[sendmsg_num]);
                                        sendmsg_num++;
                                    }
                                }
                            }).start();
                        }
                    }

                    @Override
                    public void onNotifyFailure(BleException exception) {
                        // 打开通知操作失败
                        Log.d(TAG, "onNotifyFailure:打开通知操作失败 " + bleDevice.getName());
                    }

                    @Override
                    public void onCharacteristicChanged(byte[] data) {
                        Log.d(TAG, "onCharacteristicChanged: --设备发过来的数据------>>>>>  " + MyFunc.ByteArrToHex(data));
                        // 打开通知后，设备发过来的数据将在这里出现
                        if (onGetDataListener != null) {
                            if (bleDevice.getName().startsWith("T405i")){
                                onGetDataListener.status("T405i", data, bleDevice.getRssi());
                            }
                            if (bleDevice.getName().startsWith("T410i")){
                                onGetDataListener.status("T410i", data, bleDevice.getRssi());
                            }
                            if (bleDevice.getName().startsWith("T805i")){
                                onGetDataListener.status("T805i", data, bleDevice.getRssi());
                            }

                            if (bleDevice.getName().startsWith("UT383BT")){
                                onGetDataListener.status("UT383BT", data, bleDevice.getRssi());
                            }
                        }
                    }
                });
    }

    private void sendAsk() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (isRun) {
                    try {
                        Thread.sleep(1000);
                        if (isConntedNotify) {
                            sendHexToUld("5E");
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    public void destroy() {
        _All = false;
        //终止扫描
        BleManager.getInstance().cancelScan();
        if (mDtDevice != null && notifyDtBgc != null) {
            BleManager.getInstance().stopNotify(mDtDevice, notifyDtBgc.getService().getUuid().toString(), notifyDtBgc.getUuid().toString());
        }

        if (mUldDevice != null && notifyUldBgc != null) {
            BleManager.getInstance().stopNotify(mUldDevice, notifyUldBgc.getService().getUuid().toString(), notifyUldBgc.getUuid().toString());
        }

        BleManager.getInstance().destroy();
    }


    private void sendHexToDt(String inHex) {
        BleManager.getInstance().write(
                mDtDevice,
                writeDtBGC.getService().getUuid().toString(),
                writeDtBGC.getUuid().toString(),
                hexToByteArr(inHex),
                new BleWriteCallback() {
                    @Override
                    public void onWriteSuccess(int current, int total, byte[] justWrite) {
                        // 发送数据到设备成功（分包发送的情况下，可以通过方法中返回的参数可以查看发送进度）
                    }

                    @Override
                    public void onWriteFailure(BleException exception) {
                        // 发送数据到设备失败
                    }
                });
    }

    private void sendHexToUld(String inHex) {
        BleManager.getInstance().write(
                mUldDevice,
                writeUldBGC.getService().getUuid().toString(),
                writeUldBGC.getUuid().toString(),
                hexToByteArr(inHex),
                new BleWriteCallback() {
                    @Override
                    public void onWriteSuccess(int current, int total, byte[] justWrite) {
                        // 发送数据到设备成功（分包发送的情况下，可以通过方法中返回的参数可以查看发送进度）
                    }

                    @Override
                    public void onWriteFailure(BleException exception) {
                        // 发送数据到设备失败
                    }
                });
    }

    //转hex字符串转字节数组
    static public byte[] hexToByteArr(String inHex)//hex字符串转字节数组
    {
        int hexlen = inHex.length();
        byte[] result;
        if (isOdd(hexlen) == 1) {//奇数
            hexlen++;
            result = new byte[(hexlen / 2)];
            inHex = "0" + inHex;
        } else {//偶数
            result = new byte[(hexlen / 2)];
        }
        int j = 0;
        for (int i = 0; i < hexlen; i += 2) {
            result[j] = HexToByte(inHex.substring(i, i + 2));
            j++;
        }
        return result;
    }


    // 判断奇数或偶数，位运算，最后一位是1则为奇数，为0是偶数
    static public int isOdd(int num) {
        return num & 0x1;
    }

    //-------------------------------------------------------
    static public byte HexToByte(String inHex)//Hex字符串转byte
    {
        return (byte) Integer.parseInt(inHex, 16);
    }

    //-------------------------------------------------------
    static public String Byte2Hex(Byte inByte)//1字节转2个Hex字符
    {
        return String.format("%02x", inByte).toUpperCase();
    }

    //-------------------------------------------------------
    static public String ByteArrToHex(byte[] inBytArr)//字节数组转转hex字符串
    {
        StringBuilder strBuilder = new StringBuilder();
        int j = inBytArr.length;
        for (int i = 0; i < j; i++) {
            strBuilder.append(Byte2Hex(inBytArr[i]));
            strBuilder.append(" ");
        }
        return strBuilder.toString();
    }


    public void setOnGetDataListener(@Nullable OnGetDataListener listener) {
        this.onGetDataListener = listener;
    }

    public void setOnConnectedListener(@Nullable OnConnectedListener listener) {
        this.onConnectedListener = listener;
    }

    public void setOnDisConnectedListener(@Nullable OnDisConnectedListener listener) {
        this.onDisConnectedListener = listener;
    }

    /**
     * 获取数据
     */
    public interface OnGetDataListener {
        void status(String type, byte[] data, int assi);
    }

    /**
     * 连接
     */
    public interface OnConnectedListener {
        void connected(String type, Long time);
    }

    /**
     * 失去连接
     */
    public interface OnDisConnectedListener {
        void disConnected(String type, Long time);
    }

}
